package xj.graph2d.tree;

import java.util.Iterator;
import java.util.Map;

import javax.swing.*;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.TreeNode;
import javax.swing.tree.TreePath;

import xj.graph2d.DrawShape;
import xj.graph2d.Group;
import xj.graph2d.app.GraphApp;
import xj.graph2d.graph.GraphComponent;
import xj.graph2d.graph.GraphEdge;
import xj.graph2d.graph.GraphNode;
import xj.graph2d.graph.HyperGraphNode;

public class GraphDocumentTreePane extends DocumentTreePane {

  public GraphDocumentTreePane(GraphApp main, Map<String, Icon> icons) {
    super(main, icons);
    showAtomicDeatil = false;
  }

  @Override
  protected void buildDocumentTree() {
    if (doc != null) {
      super.buildDocumentTree();
      nodeSet = new GraphTreeNode(GraphTreeNode.GRAPH_NODE_SET);
      edgeSet = new GraphTreeNode(GraphTreeNode.GRAPH_EDGE_SET);
      model.insertNodeInto(nodeSet, root, 0);
      model.insertNodeInto(edgeSet, root, 1);
    }
  }

  @Override
  protected void refreshTree() {
    removeAllTreeNodes(root);
    removeAllTreeNodes(nodeSet);
    removeAllTreeNodes(edgeSet);

    root.setDocument(doc);

    Iterator iter = doc.iterator();
    while (iter.hasNext()) {
      DrawShape shape = (DrawShape) iter.next();
      if (shape != null) {
	if (shape instanceof GraphNode) {
	  buildTreeNode(nodeSet, shape);
	} else if (shape instanceof GraphEdge) {
	  buildTreeNode(edgeSet, shape);
	} else {
	  buildTreeNode(root, shape);
	}
      }
    }

    Group group = doc.getGroup();
    if (group != null) {
      iter = group.allShapes();
      while (iter.hasNext()) {
	DrawShape shape = (DrawShape) iter.next();
	if (shape != null) {
	  buildTreeNode(root, shape);
	}
      }
    }

    TreeNode[] nodes = root.getPath();
    TreePath path = new TreePath(nodes);
    tree.expandPath(path);

    validate();
  }

  @Override
  protected DrawShapeTreeNode findTreeNode(DrawShape shape) {
    DrawShapeTreeNode n = null;
    n = findTreeNode(nodeSet, shape);
    if (n == null) {
      n = findTreeNode(edgeSet, shape);
    }
    if (n == null) {
      n = findTreeNode(root, shape);
    }
    return n;
  }

  @Override
  public void shapeAdded(DrawShape shape) {
    // System.out.println("GraphDocumentTreePane.shapeAdded()");

    if (shape != null) {
      DrawShapeTreeNode n;
      DrawShape parent = shape.getParent();

      if (shape instanceof GraphComponent) {
	if (parent instanceof HyperGraphNode) {
	  DrawShapeTreeNode pnode = findTreeNode(parent);
	  n = buildTreeNode(pnode, shape);
	} else {
	  if (shape instanceof GraphNode) {
	    n = buildTreeNode(nodeSet, shape);
	  } else if (shape instanceof GraphEdge) {
	    n = buildTreeNode(edgeSet, shape);
	  } else {
	    n = buildTreeNode(root, shape);
	  }
	}
      } else {
	if (parent != null) {
	  DrawShapeTreeNode pnode = findTreeNode(parent);
	  n = buildTreeNode(pnode, shape);
	} else {
	  n = buildTreeNode(root, shape);
	}
      }

      /*
       * if (parent != null) { DrawShapeTreeNode pnode = findTreeNode(parent);
       * n = buildTreeNode(pnode, shape); } else { if (shape instanceof
       * GraphNode) { n = buildTreeNode(nodeSet, shape); } else if (shape
       * instanceof GraphEdge) { n = buildTreeNode(edgeSet, shape); } else { n =
       * buildTreeNode(root, shape); } }
       */

      if (n != null) {
	TreeNode[] nodes = n.getPath();
	TreePath path = new TreePath(nodes);
	tree.setSelectionPath(path);
	validate();
      }

      if (main != null) {
	main.showShapeProperties(shape);
      }
    }
  }

  @Override
  public void clear() {
    removeAllTreeNodes(root);
    removeAllTreeNodes(nodeSet);
    removeAllTreeNodes(edgeSet);
    validate();
  }

  protected DefaultMutableTreeNode nodeSet, edgeSet;

}
